package mspbots.data.tl.prod.tsheet.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import mspbots.data.tl.base.AbstractBaseServiceImpl;
import mspbots.data.tl.prod.other.mapper.SysUserMappingMapper;
import mspbots.data.tl.prod.other.model.SysUserMapping;
import mspbots.data.tl.prod.tsheet.mapper.TsheetTimeMapper;
import mspbots.data.tl.prod.tsheet.mapper.TsheetUserMapper;
import mspbots.data.tl.prod.tsheet.model.AttendanceTsheetTime;
import mspbots.data.tl.prod.tsheet.model.TsheetsTime;
import mspbots.data.tl.prod.tsheet.model.TsheetsUser;
import mspbots.data.tl.prod.tsheet.service.TsheetsService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

/**
 * @author Jay.Yang
 */

@Service
@Log4j2
@RequiredArgsConstructor
@DS("master")
public class TsheetsServiceImpl extends AbstractBaseServiceImpl<TsheetTimeMapper, AttendanceTsheetTime>
        implements TsheetsService {

    private final SysUserMappingMapper userMappingMapper;
    private final TsheetUserMapper tsheetUserMapper;

    @Override
    public void sync(TsheetsTime sheetsTime) {

        SysUserMapping userMapping = userMappingMapper.selectOne(Wrappers.<SysUserMapping>lambdaQuery()
                .eq(SysUserMapping::getTenantCode, sheetsTime.getTenantId())
                .eq(SysUserMapping::getMappingUserId, sheetsTime.getSheetUserId().toString())
                .eq(SysUserMapping::getUserType, "3")
                .last("limit 1"));
        Long userId = ObjectUtils.isEmpty(userMapping) ? null : userMapping.getUserId();

        TsheetsUser tsheetsUser = tsheetUserMapper.selectOne(Wrappers.<TsheetsUser>lambdaQuery()
                .eq(TsheetsUser::getTenantCode, sheetsTime.getTenantId())
                .eq(TsheetsUser::getSheetUserId, sheetsTime.getSheetUserId())
                .last("limit 1"));
        String sheetUserName = null;
        if (!ObjectUtils.isEmpty(tsheetsUser)){
            String firstName = StringUtils.isEmpty(tsheetsUser.getFirstName()) ? "" : tsheetsUser.getFirstName();
            String lastName = StringUtils.isEmpty(tsheetsUser.getLastName()) ? "" : tsheetsUser.getLastName();
            sheetUserName = firstName + " " + lastName;
        }

        AttendanceTsheetTime inData = AttendanceTsheetTime.builder()
                .action("in")
                .sheetId(sheetsTime.getSheetId())
                .logTime(sheetsTime.getStartTime())
                .date(sheetsTime.getOneDay())
                .sheetUserId(sheetsTime.getSheetUserId())
                .sheetUserName(sheetUserName)
                .sysUserId(userId)
                .syncTime(LocalDateTime.now())
                .build();
        inData.setTenantCode(sheetsTime.getTenantId());

        JsonNode extend = sheetsTime.getExtend();
        inData.setLocation(ObjectUtils.isEmpty(extend.get("location")) ? null : extend.get("location").asText());
        inData.setTzStr(ObjectUtils.isEmpty(extend.get("tz_str")) ? null : extend.get("tz_str").asText());
        inData.setType(ObjectUtils.isEmpty(extend.get("type")) ? null : extend.get("type").asText());
        inData.setTz(ObjectUtils.isEmpty(extend.get("tz")) ? null : extend.get("tz").asText());
        inData.setTzTime(setTzTime(inData.getTz()));

        if ("manual".equalsIgnoreCase(inData.getType()) || ObjectUtils.isEmpty(inData.getLogTime())) {
            inData.setAction(null);
            inData.setDuration(ObjectUtils.isEmpty(sheetsTime.getDuration()) ? null : sheetsTime.getDuration() / 60);
            setManualTsheetsTime(inData);
            return;
        }

        //Does it already have the same in data
        AttendanceTsheetTime inDbData = super.baseMapper.selectOne(Wrappers.<AttendanceTsheetTime>lambdaQuery()
                .eq(AttendanceTsheetTime::getTenantCode, inData.getTenantCode())
                .eq(AttendanceTsheetTime::getAction, "in")
                .eq(AttendanceTsheetTime::getSheetId, inData.getSheetId())
                .last("limit 1"));

        if (ObjectUtils.isEmpty(inDbData)) {
            super.baseMapper.insert(inData);
        }else{
            inData.setId(inDbData.getId());
            super.baseMapper.updateById(inData);
        }

        AttendanceTsheetTime outDbData = super.baseMapper.selectOne(Wrappers.<AttendanceTsheetTime>lambdaQuery()
                .eq(AttendanceTsheetTime::getTenantCode, inData.getTenantCode())
                .eq(AttendanceTsheetTime::getAction, "out")
                .eq(AttendanceTsheetTime::getSheetId, inData.getSheetId())
                .last("limit 1"));

        if (!ObjectUtils.isEmpty(sheetsTime.getEndTime())){
            AttendanceTsheetTime outData = AttendanceTsheetTime.builder().build();
            BeanUtils.copyProperties(inData, outData);
            outData.setId(null);
            outData.setAction("out");
            outData.setLogTime(sheetsTime.getEndTime());
            outData.setDuration(ObjectUtils.isEmpty(sheetsTime.getDuration()) ? null : sheetsTime.getDuration() / 60);
            if (ObjectUtils.isEmpty(outDbData)){
                super.baseMapper.insert(outData);
            }else{
                outData.setId(outDbData.getId());
                super.baseMapper.updateById(outData);
            }
        }else if (!ObjectUtils.isEmpty(outDbData)){
            super.baseMapper.deleteById(outDbData.getId());
        }
    }

    private void setManualTsheetsTime(AttendanceTsheetTime data){
        AttendanceTsheetTime inDbData = super.baseMapper.selectOne(Wrappers.<AttendanceTsheetTime>lambdaQuery()
                .eq(AttendanceTsheetTime::getTenantCode, data.getTenantCode())
                .eq(AttendanceTsheetTime::getSheetId, data.getSheetId())
                .last("limit 1"));

        if (ObjectUtils.isEmpty(inDbData)) {
            super.baseMapper.insert(data);
        }else{
            data.setId(inDbData.getId());
            super.baseMapper.updateById(data);
        }
    }

    public String setTzTime(String tzString){
        Double tz = Double.valueOf(tzString);
        if (tzString == null){
            return "+00:00";
        }
        String result = "";
        if (!tzString.contains(".")){
            if (tzString.contains("-")){
                result += "-";
                if (tz > -10){
                    result += "0" + tzString.substring(1) + ":00";
                }else{
                    result += tzString.substring(1) + ":00";
                }
            }else{
                result += "+";
                if (tz < 10){
                    result += "0" + tzString + ":00";
                }else{
                    result += tzString + ":00";
                }
            }
        }else{
            String[] split = tzString.split("\\.");
            String min = split[0];
            String sed = split[1];
            if (min.contains("-")){
                result += "-";
                if (tz > -10){
                    result += "0" + min.substring(1) + ":";
                }else{
                    result += min.substring(1) + ":";
                }
            }else{
                result += "+";
                if (tz < 10){
                    result += "0" + min + ":";
                }else{
                    result += min + ":";
                }
            }
            int i = Integer.valueOf(sed) * 6;
            if (i < 100){
                result += i;
            }else{
                result += String.valueOf(i).substring(0,2);
            }
        }
        return result;
    }

}
